package com.example.bookstore.config.filter

import com.example.bookstore.security.JwtUser
import com.example.bookstore.security.TokenService
import org.springframework.boot.configurationprocessor.json.JSONObject
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse


/**
 * Created by IntelliJ IDEA.
 * User: lvshe
 * Date: 2019/8/13
 * Time: 20:43
 */
class GenerateTokenForUserFilter(
        path: String,
        private val tokenService: TokenService,
        private val redisTemplate: StringRedisTemplate,
        authManager: AuthenticationManager
) : AbstractAuthenticationProcessingFilter(AntPathRequestMatcher(path, "POST")) {

    init {
        this.authenticationManager = authManager
    }

    override fun attemptAuthentication(request: HttpServletRequest, response: HttpServletResponse): Authentication {
        val jsonString = String(request.inputStream.readAllBytes(), Charsets.UTF_8)
        val userJSON = JSONObject(jsonString)
        val username = userJSON.getString("username")
        val password = userJSON.getString("password")
//        val ip = request.remoteAddr
        val authToken = UsernamePasswordAuthenticationToken(username, password)
        return authenticationManager.authenticate(authToken)
    }

    override fun successfulAuthentication(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain, authResult: Authentication) {
        SecurityContextHolder.getContext().authentication = authResult
        response.status = HttpServletResponse.SC_OK
        val jwtUser = authResult.principal as JwtUser
        val tokenForUser = tokenService.createTokenForUsername(jwtUser.username)
        response.contentType = "application/json;charset=UTF-8"
        response.writer.write(MappingJackson2HttpMessageConverter().objectMapper.writeValueAsString(hashMapOf("token" to tokenForUser)))

        response.writer.flush()
        response.writer.close()
    }

    override fun unsuccessfulAuthentication(request: HttpServletRequest, response: HttpServletResponse, failed: AuthenticationException) {
        SecurityContextHolder.getContext().authentication = null
        response.status = HttpServletResponse.SC_UNAUTHORIZED
        response.contentType = "application/json;charset=UTF-8"
        val responseJson = hashMapOf("message" to failed.message)
        response.writer.write(MappingJackson2HttpMessageConverter().objectMapper.writeValueAsString(responseJson))

        response.writer.flush()
        response.writer.close()
    }


}